home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / risc_src.lha / risc_sources / sparc / expand.c < prev    next >
C/C++ Source or Header  |  1990-08-28  |  3KB  |  125 lines

  1. #include <stdio.h>
  2.  
  3. /* convert a pathname to an absolute one, if it is absolute already,
  4.    it is returned in the buffer unchanged, otherwise leading "./"s
  5.    will be removed, and "../"s will be resolved.
  6.  
  7.    In a moment of weakness, I have implemented the cshell ~ filename
  8.    convention.  ~/foobar will have the ~ replaced by the home directory of
  9.    the current user.  ~user/foobar will have the ~user replaced by the
  10.    home directory of the named user.  This should really be in the kernel
  11.    (or be replaced by a better kernel mechanism).  Doing file name
  12.    expansion like this in a user-level program leads to some very
  13.    distasteful non-uniformities.
  14.  
  15.    Another fit of dementia has led me to implement the expansion of shell
  16.    environment variables.  $HOME/mbox is the same as ~/mbox.  If the
  17.    environment variable a = "foo" and b = "bar" then:
  18.     $a      =>      foo
  19.     $a$b    =>      foobar
  20.     $a.c    =>      foo.c
  21.     xxx$a   =>      xxxfoo
  22.     ${a}!   =>      foo!
  23.  
  24.                 James Gosling @ CMU
  25.  */
  26.  
  27. /* #include <sys/types.h>
  28.    #include <sys/stat.h> */
  29. #include <pwd.h>
  30. #include "ctype.h"
  31.  
  32. expand_path (nm, buf)           /* input name in nm, absolute pathname
  33.                    output to buf.  returns 0 on success
  34.                    -1 on failure with error msg in buf  */
  35. char    *nm,
  36. * buf; {
  37.     register char  *s,
  38.            *d;
  39.     char    lnm[1000];
  40.     s = nm;
  41.     d = lnm;
  42.     while (*d++ = *s)
  43.     if (*s++ == '$') {
  44.         register char  *start = d;
  45.         register    braces = *s == '{';
  46.         register char  *value;
  47.         while (*d++ = *s)
  48.         if (braces ? *s == '}' : !(isalpha(*s) || isdigit(*s)
  49.                                || (*s == '_')))
  50.             break;
  51.         else
  52.             s++;
  53.         *--d = 0;
  54.         value = (char *) getenv (braces ? start + 1 : start);
  55.         if (value) {
  56.         for (d = start - 1; *d++ = *value++;);
  57.         d--;
  58.         if (braces && *s)
  59.             s++;
  60.         }
  61.     }
  62.     d = buf;
  63.     nm = lnm;
  64.     if (nm[0] == '~')           /* prefix ~ */
  65.     if (nm[1] == '/' || nm[1] == 0)/* ~/filename */
  66.         if (s = (char *) getenv ("HOME")) {
  67.         if (*++nm)
  68.             nm++;
  69.         }
  70.         else
  71.         s = "";
  72.     else {                  /* ~user/filename */
  73.         register char  *nnm;
  74.         register struct passwd *pw;
  75.         for (s = nm; *s && *s != '/'; s++);
  76.         nnm = *s ? s + 1 : s;
  77.         *s = 0;
  78.         pw = (struct passwd *) getpwnam (nm + 1);
  79.         if (pw == 0) {
  80.         sprintf (buf,"\"%s\" isn't a registered user.", nm+1);
  81.         return -1;
  82.         }
  83.         else {
  84.         nm = nnm;
  85.         s = pw -> pw_dir;
  86.         }
  87.     }
  88.     while (*d++ = *s++);
  89.     if (buf[0] != '\0') *(d - 1) = '/'; else d--;
  90.     s = nm;
  91.     while (*d++ = *s++);
  92.     *(d - 1) = '/';
  93.     *d = '\0';
  94.     d = buf;
  95.     s = buf;
  96.     while (*s)
  97.     if ((*d++ = *s++) == '/' && d > buf + 1) {
  98.         register char  *t = d - 2;
  99.         switch (*t) {
  100.         case '/':       /* found // in the name */
  101.             --d;
  102.             break;
  103.         case '.':
  104.             switch (*--t) {
  105.             case '/': /* found /./ in the name */
  106.                 d -= 2;
  107.                 break;
  108. #if 0
  109.             case '.':
  110.                 if (*--t == '/') {/* found /../ */
  111.                 while (t > buf && *--t != '/');
  112.                 d = t + 1;
  113.                 }
  114.                 break;
  115. #endif
  116.             }
  117.             break;
  118.         }
  119.     }
  120.     if (*(d - 1) == '/')
  121.     d--;
  122.     *d = '\0';
  123.     return 0;
  124. }
  125.